package com.qfedu.ioc.framework;

import com.qfedu.ioc.Leader;
import com.qfedu.ioc.Test2;
import com.qfedu.ioc.Water;
import com.qfedu.ioc.framework.annotation.Autowired;
import com.qfedu.ioc.framework.annotation.Component;
import com.qfedu.ioc.framework.exexetion.UnexpectedBeanDefitionalException;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static com.sun.deploy.util.SessionState.init;

public class InjectionContext {
    private final static HashMap<Class, List<Class>> fatherSonHashMap=new HashMap<>();

   public static final HashMap<String ,Object> beanMap=new HashMap<String,Object>();

   private static final List<Class> beanList=new ArrayList<>();


    private String basePackage;

    public InjectionContext() {
    }

    public InjectionContext(String basePackage) {
        this.basePackage = basePackage;

        try {
            try {
                init(basePackage);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public Object getBean(String id){
        return beanMap.get(id);
    }

    private Object inject(Class leaderClass) throws Exception {

        try {

//            Class<Leader> leaderClass= Leader.class;
            Field[] declaredFields = leaderClass.getDeclaredFields();
            String id1=getId(leaderClass);
            Object leader = beanMap.get(id1);
            if (leader==null){
                leader=leaderClass.newInstance();
                beanMap.put(id1,leader);
            }
            for (int i = 0; i < declaredFields.length; i++) {
                Field field = declaredFields[i];
                field.setAccessible(true);
                Autowired annotation = field.getAnnotation(Autowired.class);
                if (annotation!=null){
                    Class aClass = field.getType();
                    if (aClass.isInterface()){
                        List<Class> classList = fatherSonHashMap.get(aClass);
                        if(classList==null){
                            throw new NullPointerException();
                        }
                        if (classList!=null&&classList.size()==1){
                            Class sonClass = classList.get(0);
                            String id = getId(sonClass);
                            Object bean = beanMap.get(id);
                            if (bean==null){
                                Object instance = sonClass.newInstance();
                                field.set(leader,instance);
                                beanMap.put(id,instance);
                            }else {
                                field.set(leader,bean);
                            }

                        }else {
                            boolean isAutowiredFail=true;
                            for (int j = 0; j < classList.size(); j++) {
                                Class sonClass = classList.get(j);
                                String fieldName = field.getName();
                                String substring = fieldName.substring(1, fieldName.length());
                                String upperCase = fieldName.toUpperCase();
                                char firstChar = upperCase.charAt(0);
                                String className=firstChar+substring;
                                if (sonClass.getName().endsWith(className)){
                                    String id = getId(sonClass);
                                    Object bean = beanMap.get(id);
                                    if (bean==null){
                                        Object instance = sonClass.newInstance();
                                        field.set(leader,instance);
                                        beanMap.put(id,instance);
                                    }else {
                                        field.set(leader,bean);
                                    }

                                    isAutowiredFail=false;
                                }

                            }
                            if (isAutowiredFail){
                                throw new UnexpectedBeanDefitionalException("只想注入一个却注入两个，不知道注入的是哪一个");
                            }else {
                                field.set(leader,aClass.newInstance());
                            }
                        }

                    }  else {
                        String id = getId(aClass);
                        Object bean = beanMap.get(id);
                        if (bean==null){
                            Object instance = aClass.newInstance();
                            field.set(leader,instance);
                            beanMap.put(id,instance);
                        }else {
                            field.set(leader,bean);
                        }
                    }


                }

            }
            return leader;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;

    }
    private void init(String basePackage) throws Exception{
        URL resource = Test2.class.getResource("/");
        System.out.println(resource.getPath());
        String resourcePath = resource.getPath();
        String replaceAll = basePackage.replaceAll("\\.", "/");
        String path= resourcePath+replaceAll;

    File file = new File(path);
    File[] files = file.listFiles();
        for (File file1 : files) {
        String name = file1.getName();
        if (file1.isFile()&&name.endsWith(".class")){
            String[] split = name.split("\\.");
            Class<?> aClass = Class.forName(basePackage + "." + split[0]);
            Component annotation = aClass.getAnnotation(Component.class);
            if (annotation!=null){
                Class<?>[] interfaces = aClass.getInterfaces();
                for (int i = 0; i <interfaces.length ; i++) {
                    Class<?> anInterface=interfaces[i];

                    List<Class> sonList = fatherSonHashMap.get(anInterface);
                    if (sonList==null){
                        ArrayList<Class> sonClassList = new ArrayList<>();
                        sonClassList.add(aClass);
                        fatherSonHashMap.put(anInterface,sonClassList);
                    }else {
                        sonList.add(aClass);
                    }
                }
            }
        }
    }
        for (int i = 0; i < beanList.size(); i++) {
            Class aClass = beanList.get(i);
            Object object = inject(aClass);
            String id = getId(aClass);
            beanMap.put(id,object);
        }
}
private String getId(Class aClass){
    String tempId = aClass.getName();
    int lastIndexOf = tempId.lastIndexOf(".");
    tempId=tempId.substring(lastIndexOf+1,tempId.length());
    char charAt = tempId.toLowerCase().charAt(0);
    String substring = tempId.substring(1, tempId.length());
   String id= charAt+substring;
   return id;
}

}
